package logic

import (
	"context"
	"fmt"
	"github.com/pkg/errors"
	"github.com/wechatpay-apiv3/wechatpay-go/core/auth/verifiers"
	"github.com/wechatpay-apiv3/wechatpay-go/core/downloader"
	"github.com/wechatpay-apiv3/wechatpay-go/core/notify"
	"github.com/wechatpay-apiv3/wechatpay-go/services/payments"
	"net/http"
	"xialou_platform/app/errorx"
	"xialou_platform/services/agent/rpc/agentClient"
	v3 "xialou_platform/services/order/api/internal/wxpay/v3"
	"xialou_platform/services/order/model"
	"xialou_platform/services/order/rpc/orderClient"

	"xialou_platform/services/order/api/internal/svc"
	"xialou_platform/services/order/api/internal/types"

	"github.com/zeromicro/go-zero/core/logx"
)

type WxPayCallBackLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

func NewWxPayCallBackLogic(ctx context.Context, svcCtx *svc.ServiceContext) WxPayCallBackLogic {
	return WxPayCallBackLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

func (l *WxPayCallBackLogic) WxPayCallBack(rw http.ResponseWriter, req *http.Request) (resp *types.WxPayCallbackResp, err error) {
	// todo: add your logic here and delete this line
	_, err = v3.NewWxPayClientV3(l.svcCtx.Config.WxPayConf)
	if err != nil {
		return nil, err
	}

	certVisitor := downloader.MgrInstance().GetCertificateVisitor(l.svcCtx.Config.WxPayConf.MchId)
	handler := notify.NewNotifyHandler(l.svcCtx.Config.WxPayConf.APIv3Key, verifiers.NewSHA256WithRSAVerifier(certVisitor))

	logx.Infof("【微信支付回调】：certVisitor: %+v, handler: %+v", certVisitor, handler)

	transaction := new(payments.Transaction)
	_, err = handler.ParseNotifyRequest(context.Background(), req, transaction)
	if err != nil {
		logx.Errorf("微信支付回调失败, err: %s", err.Error())
		return nil, errorx.NewReasonError("微信支付回调失败", fmt.Sprintf("wechat pay callback, parse failed, err: %s", err.Error()))
	}

	logx.Infof("【微信支付回调】transaction ====> %+v", transaction)
	resp = &types.WxPayCallbackResp{
		ReturnCode: "SUCCESS",
	}

	err = l.verifyAndUpdateState(transaction)
	if err != nil {
		logx.Errorf("update state fail cause: %+v", err)
		resp.ReturnCode = "FAIL"
	}

	return resp, nil
}

var ErrWxPayCallbackError = errorx.NewDefaultError("微信支付回调失败")

func (l *WxPayCallBackLogic) verifyAndUpdateState(transaction *payments.Transaction) error {
	orderInfo, err := l.svcCtx.OrderRpc.OrderByOrderNum(l.ctx, &orderClient.OrderByOrderNumReq{
		OrderNum: *transaction.OutTradeNo,
	})
	if err != nil {
		return errors.Wrapf(ErrWxPayCallbackError, "获取流水记录失败 err:%v ,notifyTrasaction:%+v ", err.Error(), transaction)
	}
	if orderInfo.Id == 0 {
		return errorx.NewDefaultError("订单不存在")
	}
	payTotal := *transaction.Amount.Total
	if orderInfo.Money != payTotal {
		return errors.Wrapf(ErrWxPayCallbackError, "订单金额异常， notify payTotal: %v, order money: %v, transation: %v", payTotal, orderInfo.Money, transaction)
	}
	orderStatus := l.getPayStatusByWXPayTradeState(*transaction.TradeState)
	if orderStatus == model.OrderStatusSuccess {
		if orderInfo.Status != model.OrderStatusWait {
			return nil
		}

		orderInfo.Status = int64(orderStatus)
		orderInfo.TransactionId = *transaction.TransactionId

		_, err = l.svcCtx.OrderRpc.OrderUpdate(l.ctx, orderInfo)
		if err != nil {
			return errorx.NewReasonError("更新订单状态失败", err.Error())
		}

		switch orderInfo.Type {
		case 1:
			// 代理商认证
			agentParam, err := l.svcCtx.AgentRpc.AgentById(l.ctx, &agentClient.IdBody{Id: orderInfo.Uid})
			if err != nil {
				return err
			}
			agentParam.Status = 2
			_, err = l.svcCtx.AgentRpc.AgentUpdate(l.ctx, agentParam)
			if err != nil {
				return err
			}
		}

	}

	return nil
}

const (
	SUCCESS    = "SUCCESS"    //支付成功
	REFUND     = "REFUND"     //转入退款
	NOTPAY     = "NOTPAY"     //未支付
	CLOSED     = "CLOSED"     //已关闭
	REVOKED    = "REVOKED"    //已撤销（付款码支付）
	USERPAYING = "USERPAYING" //用户支付中（付款码支付）
	PAYERROR   = "PAYERROR"   //支付失败(其他原因，如银行返回失败)
	ABNORMAL   = "ABNORMAL"   // 退款异常
)

func (l *WxPayCallBackLogic) getPayStatusByWXPayTradeState(wxPayTradeState string) int32 {

	switch wxPayTradeState {
	case SUCCESS: //支付成功
		return model.OrderStatusSuccess
	case USERPAYING: //支付中
		return model.OrderStatusWait
	case REFUND: //已退款
		return model.OrderStatusRefundSuccess
	case CLOSED: // 订单关闭
		return model.OrderStatusClose
	default:
		return model.OrderStatusFAIL
	}
}
